package jamirr;

import java.lang.annotation.Annotation;
import java.util.Map;

public interface AnnotatedElement {

    /**
     * @return Whether the element is nullable.
     */
    default boolean isDeclaredNullable() {
        return hasDeclaredAnnotation(Utils.NULLABLE_ANNOTATION);
    }

    /**
     * @return Whether the element is declared as not being null
     */
    default boolean isDeclaredNonNull() {
        return hasDeclaredAnnotation(Utils.NON_NULL_ANNOTATION);
    }

    /**
     * @return Whether the element is nullable.
     */
    default boolean isNullable() {
        return hasAnnotation(Utils.NULLABLE_ANNOTATION);
    }

    /**
     * @return Whether the element is declared as not being null
     */
    default boolean isNonNull() {
        return hasAnnotation(Utils.NON_NULL_ANNOTATION);
    }

    Map<String, AnnotationMirror> getDeclaredAnnotations();

    Map<String, AnnotationMirror> getAnnotations();

    default boolean hasDeclaredAnnotation(String annotation) {
        return getDeclaredAnnotations().containsKey(annotation);
    }

    default boolean hasDeclaredAnnotation(Class<? extends Annotation> annotationType) {
        return annotationType != null && hasDeclaredAnnotation(annotationType.getName());
    }

    default boolean hasAnnotation(String annotation) {
        return getAnnotations().containsKey(annotation);
    }

    default boolean hasAnnotation(Class<? extends Annotation> annotationType) {
        return annotationType != null && hasAnnotation(annotationType.getName());
    }

    <T> T getAnnotationValue(String annotation, String member);

    default <T> T getAnnotationValue(Class<? extends Annotation> annotationType, String member) {
        return annotationType == null ? null : getAnnotationValue(annotationType.getName(), member);
    }
}
